#include "win_thread.h"
#include "exceptions.h"

// callback function used for threading
static DWORD WINAPI thread_call_back_function(LPVOID lpParam) {
  win_thread *wt = static_cast<win_thread*>(lpParam);

  if (wt != 0)
    return wt->run();
  else
    return 0;
}

////

void win_thread::release() {
  if (is_running == true) {
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);

    is_running = false;
  }
}

unsigned long win_thread::get_thread_id() const {
  return dwThreadId;
}

void win_thread::start() {
  if (is_running == true)
    return;

  stop_requested = false;

  hThread = CreateThread(
    0,                         // default security attributes
    0,                         // use default stack size
    thread_call_back_function, // thread function name
    this,                      // argument to thread function
    0,                         // use default creation flags
    &dwThreadId);              // returns the thread identifier

  if (hThread == 0)
    throw thread_exception("CreateThread failed!");

  is_running = true;
}

void win_thread::stop() {
  stop_requested = true;
  wait();
}

void win_thread::wait() {
  if (is_running == false)
    return;

  release();
}

win_thread::win_thread() : hThread(0), dwThreadId(0), is_running(false), stop_requested(false) {
  // nothing to do
}

win_thread::~win_thread() {
  release();
}
